//电子词典服务器

#include "head.h"
#define text_max 256
#define name_max 256
typedef struct message
{
	int type;
	char name[name_max];
	char data[text_max];
}MSG;
char express[256];
//全局变量用来保存查找的数据库信息
char str_global1[512];
char str_global2[512];
void do_register(int sockfd,MSG *msg_re,sqlite3 *pdb);
void do_login(int sockfd,MSG *msg,sqlite3 *pdb);
int do_search(int sockfd,MSG*msg,sqlite3 *pdbword,sqlite3*accountpdb);
void do_history(int sockfd,MSG*msg,sqlite3 *pdb);
//int callback(void *para,int f_num,char **f_value,char **f_name);
int main(int argc, const char *argv[])
{
	//创建三个数据库文件
	sqlite3 *pdb = NULL;//用来保存帐号信息
	sqlite3 *pdb_word = NULL;
	char *errmsg;//保存错误信息
	int sockfd,acceptfd;
	if(sqlite3_open("./database.db",&pdb) != 0)
	{
		fprintf(stderr,"database.db openerr:",sqlite3_errmsg(pdb));
		return -1;
	}

	if(sqlite3_open("./word.db",&pdb_word) != 0)
	{
		fprintf(stderr,"word.db openerr:",sqlite3_errmsg(pdb_word));
		return -1;
	}
	printf("数据库导入成功！\n");

	char sql1[128] = "create table account(name char primary key,passwd char,history char);";
	sqlite3_exec(pdb,sql1,NULL,NULL,&errmsg);

	char sql2[128] = "create table history(word char);";
	sqlite3_exec(pdb,sql1,NULL,NULL,&errmsg);
	printf("数据表导入成功!\n");
	

	//创建流式套接字
	sockfd = socket(AF_INET,SOCK_STREAM,0);
	if(sockfd < 0)
	{
		perror("sockfd err.");
		return -1;
	}
	
	struct sockaddr_in serveraddr;
	struct sockaddr_in clientaddr;
	serveraddr.sin_family = AF_INET;
	serveraddr.sin_port = htons(atoi(argv[1]));
	serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);

	socklen_t serlen = sizeof(serveraddr);
	socklen_t clilen = sizeof(clientaddr);

	if(bind(sockfd,(struct sockaddr*)&serveraddr,serlen)<0)
	{
		perror("bind err.");
		return -1;
	}
	printf("字典连接成功\n");
	
	if(listen(sockfd,5)<0)
	{
		perror("listen err.");
		return -1;
	}

	pid_t pid;
	//循环等待用户链接
	while(1)
	{
		acceptfd = accept(sockfd,(struct sockaddr*)&clientaddr,&clilen);
		if(acceptfd<0)
		{
			perror("acceptfd err.");
			return -1;
		}
		printf("用户登录！\n");
		//打印用户ip信息
		printf("用户 ip:%s port:%d\n",(char *)inet_ntoa(clientaddr.sin_addr.s_addr)\
		,ntohs(clientaddr.sin_port));
		pid = fork();
		//通过进程实现电子词典并发链接
		if(pid < 0)
		{
			perror("pid err.");
			return -1;
		}
		else if(pid == 0) //子进程负责发送
		{
			MSG msg;
			//子进程用来广播
			msg.type = 'B';
			while(1)
			{
				fgets(msg.data,text_max,stdin);
				//补\0
				if(msg.data[strlen(msg.data)-1] = '\n')
					msg.data[strlen(msg.data)-1] = '\0';
				send(acceptfd,&msg,sizeof(msg),0);
			}
		}else //父进程负责接收
		{
			MSG msg;
			ssize_t recvbyte;
			while(1)
			{
				 recvbyte = recv(acceptfd,&msg,sizeof(msg),0);
				 if(recvbyte < 0)
				 {
				 	perror("recv err.");
					return -1;
				 }
				 else if(recvbyte == 0)
				 {
				 	printf("用户退出!\n");
					break;
				 }
				 else
				 {
				 	switch(msg.type)
					{
						case 'L'://登录
							printf("用户正在登录！\n");
							do_login(acceptfd,&msg,pdb);
							break;
						case 'Q':
							break;
						case 'R':
							printf("用户执行注册命令\n");
							do_register(acceptfd,&msg,pdb);
							break;
						case 'S':
							printf("用户查询单词\n");
							do_search(acceptfd,&msg,pdb_word,pdb);
							break;
						case 'H':
							printf("用户查询历史\n");
							do_history(acceptfd,&msg,pdb);
						default:
							printf("server recv type err.");
							break;
					}
				 }
			}
		}

	}
	printf("end\n");
	close(sockfd);
	close(acceptfd);
	return 0;
}

void do_register(int sockfd,MSG *msg_re,sqlite3 *pdb)
{
	char sql[128];
	char *errmsg;
	printf("注册中\n");
	printf("模式:%c\n",msg_re->type);
	printf("用户名:%s\n",msg_re->name);
	printf("密码:%s \n",msg_re->data);
	sprintf(sql,"insert into account(name,passwd) values(\"%s\",\"%s\");",msg_re->name,msg_re->data);
	if(sqlite3_exec(pdb,sql,NULL,NULL,&errmsg)!=0)
	{
		perror("insert err.");
	}
	send(sockfd,msg_re,sizeof(MSG),0);
}

void do_login(int sockfd,MSG *msg,sqlite3 *pdb)
{
	MSG msg_log;
	msg_log.type = 'L';
	char *errmsg,**result;
	int ncolumn,nrow;
	char sql[128];
	sprintf(sql,"select * from account where name=\"%s\" and passwd=\"%s\";",msg->name,msg->data);
	if(sqlite3_get_table(pdb,sql,&result,&nrow,&ncolumn,&errmsg) != SQLITE_OK)
	{
		printf("login err.");
		sqlite3_free(errmsg);
	}
	if(nrow == 0)
	{
		strncpy(msg_log.data,"wrong",5);
		printf("登录失败!\n");
	}
	else
	{
		strncpy(msg_log.data,"success",7);
		printf("登录成功！\n");
	}
	send(sockfd,&msg_log,sizeof(msg_log),0);
	sqlite3_free_table(result);
}
void do_history(int sockfd,MSG*msg,sqlite3 *pdb)
{
	char sql[128];
	char *errmsg;
	MSG msg_his;
	msg_his.type = 'H';
	send(sockfd,&msg_his,sizeof(MSG),0);
}
//查询函数
int do_search(int sockfd,MSG*msg,sqlite3 *pdbword,sqlite3*accountpdb)
{
	printf("查询函数正常运行\n");
	MSG msg_ser;
	char ch[256];
	msg_ser.type = 'S';
	char *errmsg,**result;
	int nrow,ncolumn;
	char sql[128] = "";
	char sql2[128];
/*	sprintf(sql2,"insert into account(history) values(\"| %s\");",msg->name);
	if(sqlite3_exec(accountpdb,sql2,NULL,NULL,&errmsg)<0)
	{
		perror("insert history err.");
	}*/
	sprintf(sql2,"insert into history(\"%s\");",msg->name);
	if(sqlite3_exec(accountpdb,sql2,NULL,NULL,&errmsg)!= 0)
	{
				perror("history err.");
	}
	printf("%s\n",msg->name);
	sprintf(sql,"select * from word where word=\"%s\";",msg->name);
	if(sqlite3_get_table(pdbword,sql,&result,&nrow,&ncolumn,&errmsg) != SQLITE_OK)
	{
		perror("search ep err.");
		return -1;
	}
	if(nrow == 0)
	{
		printf("nrow == 0\n");
		return -1;
	}
	sprintf(ch,"%s\0",result[3]);
	printf("%s\n",ch);
	strncpy(msg_ser.data,ch,256);
	send(sockfd,&msg_ser,sizeof(MSG),0);
}
/*
int callback(void *para,int f_num,char **f_value,char **f_name)
{
	int i;
	strncpy(express,f_value[1],strlen(f_value[1]));
	return 0;
}*/
